iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
自我挑戰組

golang初探系列 第 21

day21-Interface 及 Type Assertions

  • 分享至 

  • xImage
  •  

Interface

在寫程式當中,因應需求需要運用到多個三方套件,為了讓程式碼來達到開放封閉原則
我們經常會使用到 interface
interface 的運用可以提高高內聚,低耦合(high cohesion、low coupling)
在其他語言上也有 interface 的觀念,在 golang 當中還是略有些不同
在 oop 當中的 interface 比較像是公約、規則,
oop implement interface 過程當中會思考物件行為是否符合條件並實作細節
在 golang 當中 interface 是一組 method 簽名,當類型有 implement interface mthdos時,即表示擁有有這項行為能力

package main

import "fmt"

func main() {
	p := Phone{}
	c := Camera{}
	computer := Computer{}
	computer.Working(p)
	computer.Working(c)
}

type Usb interface {
	Start()
	Stop()
}



type Phone struct {
}

func (p Phone) Start() {
	fmt.Println("手機開始工作")
}

func (p Phone) Stop() {
	fmt.Println("手機開始工作")
}

type Camera struct {
}

func (c Camera) Start() {
	fmt.Println("相機開始工作")
}

func (c Camera) Stop() {
	fmt.Println("相機開始工作")
}

type Computer struct{}

func (c Computer) Working(u Usb) {
	u.Start()
	u.Stop()
}

空街口

不包含任何的方法,所有類型的值都實現空接口,因此空接口可以存儲任意類型的數值
可以看出 fmt package 很多方法允許接收任意類型的數值

package main

import "fmt"

func main() {

	var a A = Phone{"iphone 8"}
	var a1 A = Person{"jhon", 20}
	var a2 A = 123
	var a3 A = "test"
	fmt.Println(a)
	fmt.Println(a1)
	fmt.Println(a2)
	fmt.Println(a3)
}
//空街口,代表可以是任意的值
type A interface {
}

type Phone struct {
	Type string
}

type Person struct {
	name string
	age  int
}

Type Assertions

可以藉由類型斷言來判斷 interface 原先的類型為何
藉由 fmt.Println() 為例,可以查看出 printArg method 也是用 Type Assertions 方式來推算出類型

package main

import (
	"fmt"
	"math"
)

func main() {
	var t = Triangle{3, 4, 5}
	fmt.Println(t.perimeter())
	fmt.Println(t.area())
	fmt.Println(t.a, t.b, t.c)
	var c = Circle{4}
	fmt.Println(c.perimeter())
	fmt.Println(c.area())
	fmt.Println(c.radius)
	assertType(t)
	assertType(c)
	assertType2(t)
	assertType2(c)

}

func assertType(s Shape) {
	if t, ok := s.(Triangle); ok {
		fmt.Printf("類行為三角形 三邊長為 %f,%f,%f\n", t.a, t.b, t.c)
	} else if t, ok := s.(Circle); ok {
		fmt.Printf("類行為圓形類型 %+v", t)
	} else {
		fmt.Printf("其他類型 %+v", s)
	}
}
func assertType2(s Shape) {
	switch t := s.(type) {
	case Shape:
		fmt.Println("圓形", t)
	case Triangle:
		fmt.Println("三角形", t)
	default:
		fmt.Println("其他類型 ", t)
	}

}

type Shape interface {
	perimeter() float64
	area() float64
}

type Triangle struct {
	a, b, c float64
}

func (t Triangle) perimeter() float64 {
	return t.a + t.b + t.c
}
func (t Triangle) area() float64 {
	p := t.perimeter() / 2
	s := math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
	return s
}

type Circle struct {
	radius float64
}

func (c Circle) perimeter() float64 {
	return c.radius * 2
}

func (c Circle) area() float64 {
	return math.Pow(c.radius, 2) * math.Pi
}


上一篇
day20-defer 及 錯誤處理
下一篇
day22-Error
系列文
golang初探30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言